package ru.inse.core.domain.realty;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


/**
 * Типы объектов недвижимоти
 * @author evga
 *
 */
public class RealtyObjectType
{
    static final private Map<Long, RealtyObjectType> mapById = new LinkedHashMap<Long, RealtyObjectType>();
    static final private Map<RealtyRubric, List<RealtyObjectType>> mapByRubric = new LinkedHashMap<RealtyRubric, List<RealtyObjectType>>();
    static private RealtyObjectType [] array;
    
    static final private RealtyRubric [] rubrics1 = new RealtyRubric[]
    {
        RealtyRubric.LEASE_DAILY
    };
    
    static final private RealtyRubric [] rubrics2 = new RealtyRubric[]
    {
        RealtyRubric.SELL, RealtyRubric.BUY, RealtyRubric.LEASE, RealtyRubric.RENT
    };

    static final private RealtyRubric [] rubrics3 = new RealtyRubric[]
    {
        RealtyRubric.CHANGE
    };
    
    static final public RealtyObjectType DAILY_HOUR = new RealtyObjectType(100L, rubrics1, "realty.objectType.daily_hour"); //Сдаваемая посуточно
    static final public RealtyObjectType RESIDENTIAL = new RealtyObjectType(200L, rubrics2, "realty.objectType.residential"); //Жилая
    static final public RealtyObjectType LAND = new RealtyObjectType(300L, rubrics2, "realty.objectType.land"); //Земельные участки
    static final public RealtyObjectType GARAGE = new RealtyObjectType(400L, rubrics2, "realty.objectType.garage"); //Гаражи, парковки
    static final public RealtyObjectType COMMERCE = new RealtyObjectType(500L, rubrics2, "realty.objectType.commerce"); //Коммерческая недвижимость
    static final public RealtyObjectType CHANGE = new RealtyObjectType(600L, rubrics3, "realty.objectType.change"); //Обмен недвижимостью
    
    
    final private Long id;
    final private String labelId;
    final private RealtyRubric [] rubrics;

    private RealtyObjectType(Long id, RealtyRubric [] rubrics, String label)
    {
        this.id = id;
        this.labelId = label;
        mapById.put(id, this);
        this.rubrics = rubrics;
        putByRubric(this, rubrics);
        array = null;
    }

    public RealtyRubric [] getRubrics()
    {
        return rubrics;
    }
    
    public RealtyRubric getDefaultRubric()
    {
        return rubrics[0];
    }

    static public RealtyObjectType getDefaultByRubric(RealtyRubric rubric)
    {
        List<RealtyObjectType> list = mapByRubric.get(rubric);
        return (list == null || list.isEmpty()) ? null : list.get(0);
    }
    
    static private void putByRubric(RealtyObjectType type, RealtyRubric [] rubrics)
    {
        synchronized (mapByRubric)
        {
            for (RealtyRubric rubric : rubrics)
            {
                List<RealtyObjectType> list = mapByRubric.get(rubric);
                if (list == null)
                {
                    if (list == null)
                    {
                        list = new LinkedList<RealtyObjectType>();
                    }
                }
                if (!list.contains(type))
                {
                    list = new LinkedList<RealtyObjectType>(list);
                    list.add(type);
                }
                mapByRubric.put(rubric, Collections.unmodifiableList(list));

            }
        }
    }

    public Long getId()
    {
        return id;
    }

    public String getLabelId()
    {
        return labelId;
    }
    
    public static List<RealtyObjectType> getByRubric(RealtyRubric rubric)
    {
        List<RealtyObjectType> result = mapByRubric.get(rubric);
        return result != null ? result :  Collections.<RealtyObjectType>emptyList();
    }

    static public RealtyObjectType getById(Long id)
    {
        return mapById.get(id);
    }
    
    @Override
    public String toString()
    {
        return labelId;
    }
    
    static public RealtyObjectType [] list()
    {
        if (array == null)
        {
            synchronized (RealtyObjectType.class)
            {
                if (array == null)
                {
                    array = new RealtyObjectType[mapById.size()];
                    int index = 0;
                    for (RealtyObjectType r : mapById.values())
                    {
                        array[index++] = r;
                    }
                }
            }
        }
        return array;
    }
}
